#include "ClientConnectsHandler.h"

bool ClientConnectsHandler::_addClientConnect(int clientSocket, sockaddr_in clientAddr) {
    // 创建线程
    pthread_t threadId;                                                                                  // 线程id
    ThreadData* threadData = new ThreadData(clientSocket, clientAddr);                                   // 用于保存线程处理相关数据，在堆区分配内存，以防客户端连接处理器未消亡以前就被系统自动清理，从而导致无法预测的后果
    int ret = pthread_create(&threadId, NULL, ClientConnectsHandler::_handleThread, (void*)threadData);  // 创建线程，成功返回0，否则返回错误码。
    if (0 != ret) {
        PrintLine("创建线程失败 ret(Error code):[%d], threadId:[%lu]", ret, threadId);
        return false;
    }
    PrintLine("创建线程成功 ret:[%d], threadId:[%lu]", ret, threadId);

    return true;
}

void* ClientConnectsHandler::_handleThread(void* data) {
    // 指向保存线程处理相关数据的堆区内存，方便类型转换和内存释放
    ThreadData* threadData = (ThreadData*)data;
    // 处理客户端请求数据
    ClientSocketHandler clientSocketHandler(threadData->clientSocket);
    // 死循环（处理完一次请求后，继续阻塞等待新的请求）
    while (1) {
        // 解析请求数据
        ClientRequestAnalyzer clientRequestAnalyzer(&clientSocketHandler);
        // 判断是否解析成功（解析失败，直接退出）
        if (false == clientRequestAnalyzer._isAnalyzeSuccessed()) {
            PrintLine("退出客户端请求数据处理方法");
            break;
        }

        // 测试：解析请求数据
        PrintLine("request name: [%s]", clientRequestAnalyzer._getRequestName().c_str());
        PrintLine("request url : [%s]", clientRequestAnalyzer._getUrl().c_str());
        PrintLine("http verion : [%s]", clientRequestAnalyzer._getHttpVersion().c_str());
        PrintLine("sec-ch-ua-platform: [%s]", clientRequestAnalyzer._getDataByKey("sec-ch-ua-platform").c_str());

        // 拼接文件路径
        std::string rootPath = "/home/youshao/web_file_manager";                                 // 服务器根目录
        std::string localPath = UrlConverter::_convertFromUrl(clientRequestAnalyzer._getUrl());  // url转成二进制字符
        std::string absolutePath = rootPath + localPath;                                         // 绝对路径

        // 文件处理器（获取文件信息）
        FileHandler fileHandler(absolutePath);

        // 发送响应头
        std::string header = "HTTP/1.1 200 OK\r\nServer:Httpd/1.1\r\n";
        header += "Content-Length:" + std::to_string(fileHandler._getFileSize()) + "\r\n";  // 指定文件长度（ls -al 命令查看），文件长度如何获取呢，我们写一个类专门负责获取文件信息
        header += "Content-type:image/jpeg\r\n\r\n";
        clientSocketHandler._writeSocket(header.c_str(), header.length());

        // 测试：Url和二进制字符串的互转
        PrintLine("local path [%s]", localPath.c_str());
        PrintLine("convert to url [%s]", UrlConverter::_convertToUrl(localPath).c_str());

        // 发送文件
        Tools::_sendFile(absolutePath, &clientSocketHandler);
    }

    delete (threadData);  // 释放堆区内存
    return NULL;
}

ClientConnectsHandler::ThreadData::ThreadData(int socket, sockaddr_in addr) {
    this->clientSocket = socket;
    this->clientAddr = addr;
}